#include "analyzer.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <cmath>

using namespace std;
using namespace TechnicalAnalysis;

// 计算移动平均
vector<double> TechnicalAnalysis::calculateMA(const vector<double>& prices, int period) {
    vector<double> ma;
    if (prices.size() < period) return ma;

    ma.reserve(prices.size() - period + 1);
    for (size_t i = period-1; i < prices.size(); ++i) {
        double sum = accumulate(prices.begin() + i - period + 1, prices.begin() + i + 1, 0.0);
        ma.push_back(sum / period);
    }
    return ma;
}

// 计算MACD
void TechnicalAnalysis::calculateMACD(const vector<double>& prices,
                                    vector<double>& dif,
                                    vector<double>& dea,
                                    vector<double>& macd) {
    // 简化的MACD计算逻辑
    if (prices.size() < 26) return;

    dif.resize(prices.size());
    dea.resize(prices.size());
    macd.resize(prices.size());

    // 实际实现应包含EMA计算等
    for (size_t i = 25; i < prices.size(); ++i) {
        dif[i] = prices[i] - accumulate(prices.begin() + i - 12, prices.begin() + i + 1, 0.0) / 12;
        dea[i] = accumulate(dif.begin() + i - 9, dif.begin() + i + 1, 0.0) / 9;
        macd[i] = 2 * (dif[i] - dea[i]);
    }
}

// 计算KDJ
void TechnicalAnalysis::calculateKDJ(const vector<double>& highs,
                                   const vector<double>& lows,
                                   const vector<double>& closes,
                                   vector<double>& k,
                                   vector<double>& d,
                                   vector<double>& j) {
    if (highs.size() < 9) return;

    k.resize(highs.size());
    d.resize(highs.size());
    j.resize(highs.size());

    for (size_t i = 8; i < highs.size(); ++i) {
        double highest = *max_element(highs.begin() + i - 8, highs.begin() + i + 1);
        double lowest = *min_element(lows.begin() + i - 8, lows.begin() + i + 1);
        
        double rsv = (closes[i] - lowest) / (highest - lowest) * 100;
        k[i] = (2.0/3) * k[i-1] + (1.0/3) * rsv;
        d[i] = (2.0/3) * d[i-1] + (1.0/3) * k[i];
        j[i] = 3 * k[i] - 2 * d[i];
    }
}

// 计算技术指标
void StockAnalyzer::calculateTechnicalIndicators(vector<Stock>& stocks) {
    if (stocks.size() < 30) return; // 至少需要30天数据

    vector<double> prices, highs, lows, closes;
    for (const auto& s : stocks) {
        prices.push_back(s.price);
        highs.push_back(s.price * 1.02); // 模拟最高价
        lows.push_back(s.price * 0.98);   // 模拟最低价
        closes.push_back(s.price);
    }

    // 计算移动平均
    auto ma5 = calculateMA(prices, 5);
    auto ma10 = calculateMA(prices, 10);
    
    // 计算MACD
    vector<double> dif, dea, macd;
    calculateMACD(prices, dif, dea, macd);
    
    // 计算KDJ
    vector<double> k, d, j;
    calculateKDJ(highs, lows, closes, k, d, j);
    
    // 填充回Stock对象
    for (size_t i = 0; i < stocks.size(); ++i) {
        if (i >= 4) stocks[i].ma5 = ma5[i-4];
        if (i >= 9) stocks[i].ma10 = ma10[i-9];
        if (i >= 25) stocks[i].macd = macd[i];
        if (i >= 8) {
            stocks[i].kdj_k = k[i];
            stocks[i].kdj_d = d[i];
        }
    }
}

vector<Stock> StockAnalyzer::loadFromCSV(const string& filename) {
    vector<Stock> stocks;
    ifstream file(filename);
    
    if (!file.is_open()) {
        throw runtime_error("无法打开文件: " + filename);
    }

    string line;
    getline(file, line); // 跳过表头
    
    while (getline(file, line)) {
        stringstream ss(line);
        string token;
        Stock stock;
        
        try {
            // 解析CSV行
            getline(ss, token, ','); stock.code = token;
            getline(ss, token, ','); stock.name = token;
            getline(ss, token, ','); stock.price = stod(token);
            getline(ss, token, ','); stock.change_percent = stod(token);
            getline(ss, token, ','); stock.volume = stod(token);
            getline(ss, token); stock.date = token;
            
            // 验证数据
            if (stock.price <= 0 || stock.volume < 0) continue;
            
            stocks.push_back(stock);
        } catch (...) {
            continue; // 跳过格式错误行
        }
    }
    
    return stocks;
}

vector<Stock> StockAnalyzer::analyzeAndRecommend(const vector<Stock>& stocks, const string& strategy) {
    vector<Stock> recommendations;
    vector<Stock> mutableStocks = stocks;
    
    // 计算技术指标
    calculateTechnicalIndicators(mutableStocks);
    
    for (const auto& stock : mutableStocks) {
        bool isRecommended = false;
        
        if (strategy == "technical") {
            // 技术分析策略
            isRecommended = stock.change_percent > 1.0 && stock.change_percent < 5.0 &&
                           stock.volume > 100000 &&
                           stock.macd > 0 && stock.kdj_k > stock.kdj_d;
        } 
        else if (strategy == "fundamental") {
            // 基本面分析策略
            isRecommended = stock.price > 10.0 && stock.price < 100.0 &&
                          stock.volume > 50000 &&
                          stock.ma5 > stock.ma10;
        }
        else { // combined
            // 综合策略
            isRecommended = stock.change_percent > 1.0 && stock.change_percent < 5.0 &&
                          stock.volume > 100000 &&
                          stock.price > 10.0 &&
                          stock.macd > 0;
        }
        
        if (isRecommended) {
            recommendations.push_back(stock);
        }
    }
    
    // 按涨幅排序
    sort(recommendations.begin(), recommendations.end(), 
        [](const Stock& a, const Stock& b) {
            return a.change_percent > b.change_percent;
        });
    
    return recommendations;
}

void StockAnalyzer::saveRecommendations(const vector<Stock>& recommendations, const string& filename) {
    ofstream file(filename);
    
    if (!file.is_open()) {
        throw runtime_error("无法创建结果文件: " + filename);
    }
    
    // 写入表头
    file << "代码,名称,价格,涨幅(%),成交量(手),日期,5日均价,10日均价,MACD,KDJ-K,KDJ-D\n";
    
    // 写入数据
    for (const auto& stock : recommendations) {
        file << stock.code << ","
             << stock.name << ","
             << stock.price << ","
             << stock.change_percent << ","
             << stock.volume << ","
             << stock.date << ","
             << stock.ma5 << ","
             << stock.ma10 << ","
             << stock.macd << ","
             << stock.kdj_k << ","
             << stock.kdj_d << "\n";
    }
}